package com.edu.tool.service.impl.login;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.edu.tool.bean.user.SysCaptchaToken;
import com.edu.tool.exception.captcha.CaptchaException;
import com.edu.tool.mapper.user.SysCaptchaTokenMapper;
import com.edu.tool.service.user.SysCaptchaService;
import com.edu.tool.util.date.SimpleDateUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;

/**
 * @FileName：CaptchaServiceImpl.java
 * @Description：@TODO
 * @Author：thy
 * @CreateTime：上午1:07:00
 */
@Service
public class SysCaptchaServiceImpl implements SysCaptchaService {
    public static Logger logger = LoggerFactory.getLogger(SysCaptchaServiceImpl.class);


    @Autowired
    DefaultKaptcha producer;

    @Autowired
    private SysCaptchaTokenMapper captchaTokenMapper;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Map create(Integer tenantId, String clientIp) throws CaptchaException  {

        Date now = new Date();

        Date validTime = SimpleDateUtil.addMinsForDate(now, 100);
        String capText = producer.createText();
        BufferedImage image = producer.createImage(capText);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", baos);
        } catch (IOException ioe) {
            logger.error("Failed to generate captcha code: " + ioe.getMessage());
            throw new CaptchaException("Failed to get captcha code.");
        }
        byte[] bytes = baos.toByteArray();
        String captchaImage = Base64.getEncoder().encodeToString(bytes);
        String token = UUID.randomUUID().toString();

        SysCaptchaToken captchaToken= new SysCaptchaToken( validTime, token, capText, "0", 0, clientIp);

        captchaTokenMapper.insert(captchaToken);

        Map result = new HashMap();
        result.put("captchaToken", token);
        result.put("captchaImage", captchaImage);
        return result;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void verify(Integer tenantId, String captchaToken, String captcha) throws CaptchaException {

        if(captchaToken == null
                || captcha == null
                ||StringUtils.isEmpty(captcha)
                ||StringUtils.isEmpty(captchaToken)
                )
            throw new CaptchaException("验证码错误");

        Date now = new Date();

        QueryWrapper<SysCaptchaToken> queryMapper = new QueryWrapper<SysCaptchaToken>();
        LambdaQueryWrapper<SysCaptchaToken> lqw = queryMapper.lambda();
        lqw.eq(SysCaptchaToken::getToken,captchaToken);
        if(tenantId != null){
            lqw.eq(SysCaptchaToken::getTenantId,tenantId);
        }

        SysCaptchaToken sysCaptchaToken= captchaTokenMapper.selectOne(queryMapper);

        if(sysCaptchaToken == null
                ||!"0".equals(sysCaptchaToken.getStatus() )
                || now.after(sysCaptchaToken.getValidTime())
                )
        {
            throw new CaptchaException("验证码已过期");
        }
        int verifyTimes = sysCaptchaToken.getVerifyTimes()+1;

        if(!captcha.equalsIgnoreCase(sysCaptchaToken.getCaptcha()))
        {

            String status = "0";
            if(verifyTimes >= 6)
                status = "2";
            sysCaptchaToken.setStatus(status);
            sysCaptchaToken.setVerifyTimes(verifyTimes);
            captchaTokenMapper.updateById(sysCaptchaToken);

            throw new CaptchaException("验证码错误");

        }
        sysCaptchaToken.setStatus("1");
        sysCaptchaToken.setVerifyTimes(verifyTimes);
        captchaTokenMapper.updateById(sysCaptchaToken);

    }

}

